package sicnu.cs.aps.rest;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sicnu.cs.aps.common.Constants;
import sicnu.cs.aps.common.ResultInfo;
import sicnu.cs.aps.common.ResultInfoUtil;
import sicnu.cs.aps.common.annotations.OperLog;
import sicnu.cs.aps.common.enums.*;
import sicnu.cs.aps.common.util.CollectionUtil;
import sicnu.cs.aps.common.util.FileCheckUtil;
import sicnu.cs.aps.common.util.RequestUtil;
import sicnu.cs.aps.common.util.ValidateUtils;
import sicnu.cs.aps.domain.dto.ActivityFormQuestionDto;
import sicnu.cs.aps.domain.entity.*;
import sicnu.cs.aps.domain.form.*;
import sicnu.cs.aps.mapper.UserMapper;
import sicnu.cs.aps.service.*;

import javax.validation.Valid;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

/**
 * @author CaiKe
 * @date 2022/5/27 10:02
 */
@Slf4j
@RestController
@RequestMapping("/activity")
@RequiredArgsConstructor
@Api(tags = {"活动报名/管理模块"})
public class ActivitySignResource {

    private final IActivitySignService activitySignService;
    private final IActivityPlanService activityPlanService;
    private final IFileUploadService fileUploadService;
    private final IActivityService activityService;
    private final ISendMailService sendMailService;
    private final IUserService userService;
    private final ITeamMemberInviteService inviteService;
    private final ITeamMemberService teamMemberService;
    private final UserMapper userMapper;
    private final IUserInfoService userInfoService;
    private final IStudentInfoService studentInfoService;
    private final ITeacherInfoService teacherInfoService;
    private final IActivityTeamFeedbackService teamFeedbackService;
    private final IActivityRestrictionService activityRestrictionService;
    private final IActivityAuditService activityAuditService;
    private final IActivityFormStuAnswerService activityFormStuAnswerService;
    private final IActivityFormService activityFormService;
    private final IActivityFormQuestionService activityFormQuestionService;

    private Long lastTime = System.currentTimeMillis();

    @PostMapping("/sign")
    @ApiOperation("报名活动：1-创建报名信息")
    @OperLog(type = OperEnum.ADD, description = "创建报名信息")
    @PreAuthorize("hasAnyRole('ROLE_STUDENT','ROLE_TEACHER')")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> signUpActivity(@RequestBody @Valid ActivityTeamForm activityTeamForm) {
        final long start = System.currentTimeMillis();
        /*
        学院、专业、年级、性别、小队数量限制
        查出活动限制表，挨个比对
         */
//        //printTimeGap("开始校验学院、年级、性别");
        ActivityRestriction activityRestriction = activityRestrictionService.getById(activityTeamForm.getActivityId());
        //如果是学生
        if (RequestUtil.getCurrentUserRole().contains(Constants.ROLE_STUDENT)) {
            //限制学院
            StudentInfo studentInfo = studentInfoService.getById(RequestUtil.getCurrentUserId());
            if (!activityRestriction.getCollegeIds().isBlank()) {
                String[] collegeIds = activityRestriction.getCollegeIds().split("\\|");
                if (Arrays.stream(collegeIds).noneMatch(s -> s.equals(studentInfo.getCollegeId().toString()))) {
                    return ResultInfoUtil.buildError("您不属于该活动规定的学院，无法报名");
                }
            }
            //限制年级
            if (!activityRestriction.getGrades().isBlank()) {
                String[] grades = activityRestriction.getGrades().split("\\|");
                if (Arrays.stream(grades).noneMatch(s -> s.equals(studentInfo.getGrade().toString()))) {
                    return ResultInfoUtil.buildError("您不属于该活动规定的年级，无法报名");
                }
            }
            //限制性别
            Integer sex = activityRestriction.getSex();
            if (!sex.equals(0)) {
                if (!studentInfo.getGender().equals(sex)) {
                    return ResultInfoUtil.buildError("您不属于该活动规定的性别，无法报名");
                }
            }
            //如果是老师
        } else {
            return ResultInfoUtil.buildError("只有学生可以报名活动");
        }
        //限制小队数量
//        //printTimeGap("开始校验小队数量");
        List<Long> teamIdList = activitySignService.selectTeamIdByActivityId(activityTeamForm.getActivityId());
        if (!activityRestriction.getActivitySize().equals(-1)) {
            if (teamIdList.size() >= activityRestriction.getActivitySize()) {
                return ResultInfoUtil.buildError("该活动报名队伍数量已达上限，无法报名");
            }
        }
        /*
        创建报名信息并存储
         */
//        //printTimeGap("获取活动信息");
        Activity activity = activityService.getById(activityTeamForm.getActivityId());
        // 判断当前用户是否已经报名过该活动
//        //printTimeGap("判断用户是否已报名");
        QueryWrapper<ActivityTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", RequestUtil.getCurrentUserId())
                .eq("activity_id", activityTeamForm.getActivityId());

        int count = activitySignService.count(queryWrapper);
        if (count > 0) {
            return ResultInfoUtil.buildError("您已经报名过当前活动，不可重复报名");
        }
        // 判断创建报名信息时间必须早于活动报名截止时间
        if (!new Date().before(activity.getSignEndTime())) {
            return ResultInfoUtil.buildError("创建报名信息时间必须早于活动报名截止时间");
        }

//        //printTimeGap("开始保存报名信息");
        var activityTeamToSave = ActivityTeam.builder()
                .name(activityTeamForm.getName())
                .userId(RequestUtil.getCurrentUserId())
                .activityId(activityTeamForm.getActivityId())
                .status(ActivitySignEnum.SIGN_PASS_NO_PLAN)
                .build();
        activitySignService.save(activityTeamToSave);
        /*
        将队长存入队伍成员信息表
         */
//        //printTimeGap("开始保存队伍信息");
        Long teamId = activityTeamToSave.getId();
        var activityTeamMemberToSave = TeamMember.builder()
                .teamId(teamId)
                .userId(RequestUtil.getCurrentUserId())
                .type(ActivityTeamMemberInviteEnum.INVITE_AS_TEAM_LEADER.getIndex())
                .build();
        teamMemberService.save(activityTeamMemberToSave);
        /*
        如果有，邀请指导老师
         */
        if (activityTeamForm.getTeacherId() != null) {
            ////printTimeGap("开始邀请指导老师");
            activitySignService.inviteTeacherWhenSignup(RequestUtil.getCurrentUserId(), activityTeamForm.getTeacherId(), activityTeamToSave, activity);
        }
        /*
        如果有，邀请队伍成员
         */
        if (activityTeamForm.getMemberIds() != null && activityTeamForm.getMemberIds().size() > 0) {
            ////printTimeGap("开始邀请队员");
            activitySignService.inviteStudentsWhenSignup(RequestUtil.getCurrentUserId(), activityTeamForm.getMemberIds(), activityTeamToSave, activity);
        }

        /*
        将问卷答案存入答案信息表
         */

        ////printTimeGap("保存问卷答案");
        String answers = String.join("|", activityTeamForm.getAnswers());
        var activityFormStuAnswerToSave = ActivityFormStuAnswer.builder()
                .teamId(teamId)
                .answers(answers)
                .build();
        activityFormStuAnswerService.save(activityFormStuAnswerToSave);
        log.info("总耗时：{}", System.currentTimeMillis() - start);
        return ResultInfoUtil.buildSuccess();
    }

    @PostMapping("/sign/complete")
    @ApiOperation("报名活动：2-填写策划")
    @OperLog(type = OperEnum.ADD, description = "填写策划")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> completeSignUpInfo(@Valid ActivityPlanForm activityPlanForm, MultipartFile file) throws IOException {

        Long teamId = activitySignService.selectTeamIdByUserIdAndActivityId(RequestUtil.getCurrentUserId(), activityPlanForm.getActivityId());
        //判断报名状态
        if (!activitySignService.getById(teamId).getStatus().equals(ActivitySignEnum.SIGN_PASS_NO_PLAN)) {
            return ResultInfoUtil.buildError("当前状态不允许填写/更改策划");
        }
        /*
        各种校验
         */
        Activity activity = activityService.getById(activityPlanForm.getActivityId());

        //  校验活动归属是否是当前账号(根据活动id查找报名人)
        List<Long> list = activitySignService.selectUserIdByActivityId(activityPlanForm.getActivityId());
        if (!list.contains(RequestUtil.getCurrentUserId())) {
            return ResultInfoUtil.buildError("您不是该活动报名人，无法填写该活动策划");
        }
        //  校验活动预计开始时间小于预计结束时间
        if (!activityPlanForm.getPlanStartTime().before(activityPlanForm.getPlanEndTime())) {
            return ResultInfoUtil.buildError("活动预计开始时间必须早于活动预计结束时间");
        }
        //  活动预计开始时间必须晚于当前时间
        if (!activityPlanForm.getPlanStartTime().after(new Date())) {
            return ResultInfoUtil.buildError("活动预计开始时间必须晚于当前时间");
        }
        //  校验活动预计截止时间晚于当前时间
        if (!activityPlanForm.getPlanEndTime().after(new Date())) {
            return ResultInfoUtil.buildError("活动预计截止时间必须晚于当前时间");
        }
        //  判断活动预计持续时间是否在活动持续时间内
        if (!(activityPlanForm.getPlanStartTime().after(activity.getActivityStartTime()) && activityPlanForm.getPlanEndTime().before(activity.getActivityEndTime()))) {
            return ResultInfoUtil.buildError("活动预计持续时间必须在活动持续时间内");
        }
        //判断当前用户是否已经填写过该活动的策划
        QueryWrapper<ActivityPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", RequestUtil.getCurrentUserId())
                .eq("activity_id", activityPlanForm.getActivityId());

        int count = activityPlanService.count(queryWrapper);
        if (count > 0) {
            return ResultInfoUtil.buildError("您已经填写过当前活动的策划，不可重复填写");
        }
        /*
        填写策划
         */
        //获取活动策划中的附件路径
        String path = "";
        if (file != null) {
            if (!file.isEmpty()) {
                if (!(FileCheckUtil.checkType(file) && FileCheckUtil.checkSize(file))) {
                    return ResultInfoUtil.buildError("文件格式不正确或文件大小不得大于10M");
                }
                path = fileUploadService.uploadFile((FileInputStream) file.getInputStream(), FileTypeEnum.ACTIVITY_PLAN_ATTACHMENT, file.getOriginalFilename());
            }
        }
        var activityPlanToSave = ActivityPlan.builder()
                .id(RequestUtil.getCurrentUserId())
                .planStartTime(activityPlanForm.getPlanStartTime())
                .planEndTime(activityPlanForm.getPlanEndTime())
                .planContent(activityPlanForm.getPlanContent())
                .activityId(activityPlanForm.getActivityId())
                .uri(path)
                .build();
        activityPlanService.save(activityPlanToSave);
        //更新报名状态
        ActivityTeam activityTeam = new ActivityTeam();
        activityTeam.setStatus(ActivitySignEnum.SIGN_COMPLETE);
        QueryWrapper<ActivityTeam> updateWrapper = new QueryWrapper<>();
        updateWrapper.eq("user_id", RequestUtil.getCurrentUserId())
                .eq("activity_id", activityPlanForm.getActivityId());
        activitySignService.update(activityTeam, updateWrapper);
        //插入审核信息表

        String username = studentInfoService.getById(RequestUtil.getCurrentUserId()).getName();
        var activityAuditToSave = ActivityAudit.builder()
                .activityId(activityPlanForm.getActivityId())
                .auditedTeamId(teamId)
                .optionUserId(RequestUtil.getCurrentUserId())
                .optionUserName(username)
                .auditedTeamLeaderName(username)
                .type(ActivitySignEnum.SIGN_COMPLETE.getIndex())
                .opinionTime(new Date())
                .build();
        activityAuditService.save(activityAuditToSave);
        return ResultInfoUtil.buildSuccess();
    }

    @PutMapping("/sign/complete")
    @ApiOperation("报名活动：3-填写/更改策划")
    @OperLog(type = OperEnum.UPDATE, description = "填写/更改策划")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> updateSignUpInfo(ActivityPlanChangeForm planChangeForm, MultipartFile file) throws IOException {
        /*
        1.判断当前用户是否是该活动队伍的队长
        2.填写或修改策划
         */
        if (planChangeForm.getActivityId() == null) {
            return ResultInfoUtil.buildError("您输入正确的活动id");
        }
        Long teamId = activitySignService.selectTeamIdByUserIdAndActivityId(RequestUtil.getCurrentUserId(), planChangeForm.getActivityId());
        //判断报名状态
        if (!activitySignService.getById(teamId).getStatus().equals(ActivitySignEnum.SIGN_PASS_NO_PLAN)) {
            return ResultInfoUtil.buildError("当前状态不允许填写/更改策划");
        }

        //判断当前用户是否是队长
        if (teamId == null) {
            return ResultInfoUtil.buildError("您不是该活动队伍的队长，无法填写/更改策划");
        }

        Activity activity = activityService.getById(planChangeForm.getActivityId());
        //  校验活动预计开始时间小于预计结束时间


        /*
        1.判断策划是否已经存在
        2.如果存在，先判断新策划附件路径是否为空，如果不是，判断原策划附件路径是否为空，不为空，删除并赋予新值
        3.如果不存在，创建策划
         */

        //判断目标策划是否存在并获取附件uri
        String path = null;
        if (file != null) {
            if (!file.isEmpty()) {
                if (!(FileCheckUtil.checkType(file) && FileCheckUtil.checkSize(file))) {
                    return ResultInfoUtil.buildError("文件格式不正确或文件大小不得大于10M");
                }
                path = fileUploadService.uploadFile((FileInputStream) file.getInputStream(), FileTypeEnum.ACTIVITY_PLAN_ATTACHMENT, file.getOriginalFilename());
            }
        }
        ActivityPlan activityPlan1 = activityPlanService.getPlanByTeamId(teamId);
        if (activityPlan1 != null) {
            log.info("您已经填写过策划，现在进行更改");
            var activityPlanToSaveOrUpdate = ActivityPlan.builder()
                    .id(RequestUtil.getCurrentUserId())
                    .activityId(planChangeForm.getActivityId())
                    .planContent(planChangeForm.getPlanContent())
                    .build();
            /*
            判断时间是否正常，如果不正常，不设置，如果正常，判断是否符合逻辑，如果符合，set，不符合，返回错误
             */
            if (planChangeForm.getActivityTime() != null) {
                if (planChangeForm.getActivityTime().size() != 2) {
                    return ResultInfoUtil.buildError("请输入正确的活动预计开始与结束时间");
                }
            }
            if (!planChangeForm.getActivityTime().get(0).before(planChangeForm.getActivityTime().get(1))) {
                return ResultInfoUtil.buildError("活动预计开始时间必须早于活动预计结束时间");
            }
            //  活动预计开始时间必须晚于当前时间
            if (!planChangeForm.getActivityTime().get(0).after(new Date())) {
                return ResultInfoUtil.buildError("活动预计开始时间必须晚于当前时间");
            }
            //  校验活动预计截止时间晚于当前时间
            if (!planChangeForm.getActivityTime().get(1).after(new Date())) {
                return ResultInfoUtil.buildError("活动预计截止时间必须晚于当前时间");
            }
            //  判断活动预计持续时间是否在活动持续时间内
            if (!(planChangeForm.getActivityTime().get(0).after(activity.getActivityStartTime()) && planChangeForm.getActivityTime().get(1).before(activity.getActivityEndTime()))) {
                return ResultInfoUtil.buildError("活动预计持续时间必须在活动持续时间内");
            }
            activityPlanToSaveOrUpdate.setPlanStartTime(planChangeForm.getActivityTime().get(0));
            activityPlanToSaveOrUpdate.setPlanEndTime(planChangeForm.getActivityTime().get(1));

            if (path != null) {
                if (activityPlan1.getUri() != null && !"".equals(activityPlan1.getUri())) {
                    fileUploadService.deleteFile(activityPlan1.getUri());
                    activityPlanToSaveOrUpdate.setUri(path);
                }
            }
            UpdateWrapper<ActivityPlan> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", RequestUtil.getCurrentUserId())
                    .eq("activity_id", planChangeForm.getActivityId());
            activityPlanService.update(activityPlanToSaveOrUpdate, updateWrapper);
        } else {
            log.info("现在进行创建策划");
            if (planChangeForm.getActivityTime() == null) {
                return ResultInfoUtil.buildError("请输入正确的活动预计开始与结束时间");
            } else if (planChangeForm.getActivityTime().isEmpty()) {
                return ResultInfoUtil.buildError("请输入正确的活动预计开始与结束时间");
            } else if (planChangeForm.getActivityTime().size() != 2) {
                return ResultInfoUtil.buildError("请输入正确的活动预计开始与结束时间");
            }
            if (!planChangeForm.getActivityTime().get(0).before(planChangeForm.getActivityTime().get(1))) {
                return ResultInfoUtil.buildError("活动预计开始时间必须早于活动预计结束时间");
            }
            //  活动预计开始时间必须晚于当前时间
            if (!planChangeForm.getActivityTime().get(0).after(new Date())) {
                return ResultInfoUtil.buildError("活动预计开始时间必须晚于当前时间");
            }
            //  校验活动预计截止时间晚于当前时间
            if (!planChangeForm.getActivityTime().get(1).after(new Date())) {
                return ResultInfoUtil.buildError("活动预计截止时间必须晚于当前时间");
            }
            //  判断活动预计持续时间是否在活动持续时间内
            if (!(planChangeForm.getActivityTime().get(0).after(activity.getActivityStartTime()) && planChangeForm.getActivityTime().get(1).before(activity.getActivityEndTime()))) {
                return ResultInfoUtil.buildError("活动预计持续时间必须在活动持续时间内");
            }
            var activityPlanToSaveOrUpdate = ActivityPlan.builder()
                    .id(RequestUtil.getCurrentUserId())
                    .activityId(planChangeForm.getActivityId())
                    .planContent(planChangeForm.getPlanContent())
                    .planStartTime(planChangeForm.getActivityTime().get(0))
                    .planEndTime(planChangeForm.getActivityTime().get(1))
                    .build();
            if (path != null) {
                activityPlanToSaveOrUpdate.setUri(path);
            }
            activityPlanService.save(activityPlanToSaveOrUpdate);
            /*
            更新报名状态
            */
            ActivityTeam activityTeam = new ActivityTeam();
            activityTeam.setStatus(ActivitySignEnum.SIGN_COMPLETE);
            QueryWrapper<ActivityTeam> updateWrapper1 = new QueryWrapper<>();
            updateWrapper1.eq("user_id", RequestUtil.getCurrentUserId())
                    .eq("activity_id", planChangeForm.getActivityId());
            activitySignService.update(activityTeam, updateWrapper1);
            /*
            插入审核信息表
            */
            String username = userService.findUser(RequestUtil.getCurrentUserId()).getUsername();
            var activityAuditToSave = ActivityAudit.builder()
                    .activityId(planChangeForm.getActivityId())
                    .auditedTeamId(teamId)
                    .optionUserId(RequestUtil.getCurrentUserId())
                    .optionUserName(username)
                    .auditedTeamLeaderName(username)
                    .type(ActivityAuditEnum.CREATE.getIndex())
                    .opinionTime(new Date())
                    .build();
            activityAuditService.save(activityAuditToSave);
        }
        return ResultInfoUtil.buildSuccess();
    }

    @PutMapping("/sign/complete/after/audit")
    @ApiOperation("报名活动：4-驳回后更改策划")
    @OperLog(type = OperEnum.UPDATE, description = "驳回后更改策划")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> updateSignUpInfoAfterAudit(ActivityPlanChangeForm planChangeForm, MultipartFile file) throws IOException {
        if (planChangeForm.getActivityId() == null) {
            return ResultInfoUtil.buildError("您输入正确的活动id");
        }
        Long teamId = activitySignService.selectTeamIdByUserIdAndActivityId(RequestUtil.getCurrentUserId(), planChangeForm.getActivityId());
        //判断报名状态
        if (!(activitySignService.getById(teamId).getStatus().equals(ActivitySignEnum.COLLEGE_AUDIT_REBUT) || activitySignService.getById(teamId).getStatus().equals(ActivitySignEnum.UNIVERSITY_AUDIT_REBUT))) {
            return ResultInfoUtil.buildError("当前状态不允许更改策划");
        }

        //判断当前用户是否是队长
        if (teamId == null) {
            return ResultInfoUtil.buildError("您不是该活动队伍的队长，无法更改策划");
        }
        //判断目标策划是否存在并获取附件uri
        ActivityPlan activityPlan1 = activityPlanService.getPlanByTeamId(teamId);
        if (activityPlan1 == null) {
            return ResultInfoUtil.buildError("您寻找的策划不存在");
        }
        var activityPlanToUpdate = ActivityPlan.builder()
                .id(RequestUtil.getCurrentUserId())
                .activityId(planChangeForm.getActivityId())
                .planContent(planChangeForm.getPlanContent())
                .planStartTime(planChangeForm.getActivityTime().get(0))
                .planEndTime(planChangeForm.getActivityTime().get(1))
                .build();
        String path = null;
        if (file != null) {
            if (!file.isEmpty()) {
                if (!(FileCheckUtil.checkType(file) && FileCheckUtil.checkSize(file))) {
                    return ResultInfoUtil.buildError("文件格式不正确或文件大小不得大于10M");
                }
                path = fileUploadService.uploadFile((FileInputStream) file.getInputStream(), FileTypeEnum.ACTIVITY_PLAN_ATTACHMENT, file.getOriginalFilename());
            }
        }
        if (path != null) {
            fileUploadService.deleteFile(activityPlan1.getUri());
            activityPlanToUpdate.setUri(path);
        }
        UpdateWrapper<ActivityPlan> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", RequestUtil.getCurrentUserId())
                .eq("activity_id", planChangeForm.getActivityId());
        activityPlanService.update(activityPlanToUpdate, updateWrapper);
        /*
        更改活动报名状态
         */
        if (activitySignService.getById(teamId).getStatus().equals(ActivitySignEnum.COLLEGE_AUDIT_REBUT)) {
            var activityTeamToUpdate = ActivityTeam.builder()
                    .id(teamId)
                    .status(ActivitySignEnum.SIGN_COMPLETE)
                    .build();
            activitySignService.updateById(activityTeamToUpdate);
        } else {
            var activityTeamToUpdate = ActivityTeam.builder()
                    .id(teamId)
                    .status(ActivitySignEnum.UNIVERSITY_AUDIT_ON)
                    .build();
            activitySignService.updateById(activityTeamToUpdate);
        }
        /*
        插入审核信息表
         */
        String username = studentInfoService.getById(RequestUtil.getCurrentUserId()).getName();
        var activityAuditToSave = ActivityAudit.builder()
                .activityId(planChangeForm.getActivityId())
                .auditedTeamId(teamId)
                .optionUserId(RequestUtil.getCurrentUserId())
                .optionUserName(username)
                .auditedTeamLeaderName(username)
                .type(ActivityAuditEnum.REBUT.getIndex())
                .opinionTime(new Date())
                .build();
        activityAuditService.save(activityAuditToSave);
        return ResultInfoUtil.buildSuccess();
    }

    @DeleteMapping("/sign/{activityTeamId}")
    @ApiOperation("报名活动：5-删除活动报名信息")
    @OperLog(type = OperEnum.DELETE, description = "删除活动报名信息")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> deleteActivitySignInfo(@PathVariable("activityTeamId") Long activityTeamId) {
        /*
        1.判断该活动报名信息是否存在
        2.判断当前用户能否更改该活动报名信息
        3.删除活动报名信息、策划、成员
         */
        ActivityTeam activityTeam = activitySignService.getById(activityTeamId);
        if (activityTeam == null) {
            return ResultInfoUtil.buildError("该活动报名信息不存在");
        }
        if (!RequestUtil.getCurrentUserId().equals(activityTeam.getUserId())) {
            return ResultInfoUtil.buildError("您不是该活动队伍队长，无权更改信息");
        }
        //删除活动对应的队伍、策划、成员
        activitySignService.removeById(activityTeamId);
        QueryWrapper<ActivityPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", RequestUtil.getCurrentUserId())
                .eq("activity_id", activityTeam.getActivityId());
        activityPlanService.remove(queryWrapper);
        teamMemberService.removeById(activityTeamId);
        return ResultInfoUtil.buildSuccess();
    }

    @PostMapping("/sign/invite")
    @ApiOperation("报名活动：6-邀请队友")
    @OperLog(type = OperEnum.ADD, description = "邀请队友")
    @Async
    public ResultInfo<Void> inviteGroupMembers(@RequestBody ActivityTeamMemberInviteForm activityTeamMemberInviteForm) {
        /*
        判断活动是否存在
         */
        //////printTimeGap("开始邀请队员--获取活动信息");
        ActivityTeam currentTeam = activitySignService.getById(activityTeamMemberInviteForm.getActivityTeamId());
        if (currentTeam == null) {
            return ResultInfoUtil.buildError("该活动不存在");
        }
        /*
        判断当前用户是否是这个队伍的队长
         */
        //////printTimeGap("开始邀请队员--校验是否是队长");
        if (!RequestUtil.getCurrentUserId().equals(activitySignService.getById(activityTeamMemberInviteForm.getActivityTeamId()).getUserId())) {
            return ResultInfoUtil.buildError("您不是当前队伍的队长，无法邀请队友");
        }
        /*
        判断人数是否达到上限
         */
        //////printTimeGap("开始邀请队员---判断人数上限");
        ActivityRestriction activityRestriction = activityRestrictionService.getById(currentTeam.getActivityId());
        QueryWrapper<TeamMember> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("team_id", currentTeam.getId());
        if (!activityRestriction.getTeamSize().equals(-1)) {
            if (teamMemberService.count(queryWrapper) >= activityRestriction.getTeamSize()) {
                return ResultInfoUtil.buildError("您的小队人数已达上限，无法继续邀请");
            }
        }
        /*
         * 发送邀请的时候不用管被邀请人是否在其他队伍中，接收邀请的时候再做判断
         */


        //////printTimeGap("开始邀请学生---获取学生信息");
        ActivityTeam activityTeam = activitySignService.getById(activityTeamMemberInviteForm.getActivityTeamId());
        Long activityId = activityTeam.getActivityId();
        User currentUser = userService.findUser(RequestUtil.getCurrentUserId());
        List<User> userList = userMapper.selectBatchIds(activityTeamMemberInviteForm.getTeamMemberId());
        Activity activity = activityService.getById(activityTeam.getActivityId());
        String token = ValidateUtils.createValidateString(16);

        //////printTimeGap("开始邀请学生---发送邮件");
        for (User user : userList) {
            String context = currentUser.getUsername() + "邀请您参加【" + activity.getTitle()
                    + "】活动的【" + activityTeam.getName() + "】队伍,如果您同意邀请，请在24小时内点击下方链接:"
                    + Constants.APS_BASE_URL + "invite?token=" + token + "&activityId=" + activityId;
            sendMailService.sendInformEmail(user.getEmail(), context);
        }
        /*
        创建邀请成员信息并插入信息
         */

        ////printTimeGap("开始邀请学生---插入数据");
        var now = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, 1);
        Date nextDay = calendar.getTime();
        var teamMemberInviteToSave = ActivityTeamMemberInvite.builder()
                .userId(RequestUtil.getCurrentUserId())
                .type(ActivityTeamMemberInviteEnum.INVITE_AS_MEMBER.getIndex())
                .activityId(activityId)
                .token(token)
                .tokenValidTime(nextDay)
                .createTime(now)
                .build();
        inviteService.save(teamMemberInviteToSave);

        ////printTimeGap("开始邀请学生---完成");
        return ResultInfoUtil.buildSuccess();
    }

    @PostMapping("/sign/invite/teacher/{activityTeamId}/{teacherId}")
    @ApiOperation("报名活动：7-邀请指导老师")
    @OperLog(type = OperEnum.ADD, description = "邀请指导老师")
    public ResultInfo<Void> inviteGroupTeacher(@PathVariable("activityTeamId") Long activityTeamId, @PathVariable("teacherId") Long teacherId) {
        /*
        判断指导老师是否存在
         */

//        //printTimeGap("开始邀请指导老师--校验条件");
        QueryWrapper<TeacherInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("user_id", teacherId);
        if (teacherInfoService.count(queryWrapper1) < 1) {
            return ResultInfoUtil.buildError("该指导老师不存在");
        }

        /*
        判断活动是否存在
         */
        ActivityTeam currentTeam = activitySignService.getById(activityTeamId);
        if (currentTeam == null) {
            return ResultInfoUtil.buildError("该活动不存在");
        }
        //  判断当前用户是否是这个队伍的队长
        if (!RequestUtil.getCurrentUserId().equals(activitySignService.getById(activityTeamId).getUserId())) {
            return ResultInfoUtil.buildError("您不是当前队伍的队长，无法邀请队友");
        }
        //判断指导老师是否和队长同一学院
        if (!studentInfoService.getById(RequestUtil.getCurrentUserId()).getCollegeId().equals(teacherInfoService.getById(teacherId).getCollegeId())) {
            return ResultInfoUtil.buildError("您只能邀请同学院的指导老师");
        }

        /*
        给指导老师发邮件 谁 邀请您 参加 哪个活动的 哪个队伍 ，如果同意，请在24小时内点击下方链接
        哪个活动 队伍id-》活动id-》活动名称
         */

        //printTimeGap("开始邀请指导老师-发送邮件");
        User currentUser = userService.findUser(RequestUtil.getCurrentUserId());
        String activityTitle = activityService.getById(activitySignService.getById(activityTeamId).getActivityId()).getTitle();
        String activityTeamName = activitySignService.getById(activityTeamId).getName();
        String token = ValidateUtils.createValidateString(16);
        String context = currentUser.getUsername() + "邀请您作为指导老师参加【" + activityTitle
                + "】活动的【" + activityTeamName + "】队伍,如果您同意邀请，请在24小时内点击下方链接:"
                + Constants.APS_BASE_URL + "invite?token=" + token + "&activityId=" + activitySignService.getById(activityTeamId).getActivityId();
        sendMailService.sendInformEmail(userService.findUser(teacherId).getEmail(), context);
        /*
        创建邀请指导老师信息并插入信息
         */
        //printTimeGap("开始邀请指导老师-保存Token");
        var now = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, 1);
        Date nextDay = calendar.getTime();
        var teamMemberInviteToSave = ActivityTeamMemberInvite.builder()
                .userId(RequestUtil.getCurrentUserId())
                .type(ActivityTeamMemberInviteEnum.INVITE_AS_TEACHER.getIndex())
                .activityId(activitySignService.getById(activityTeamId).getActivityId())
                .token(token)
                .tokenValidTime(nextDay)
                .createTime(now)
                .build();
        inviteService.save(teamMemberInviteToSave);
        //printTimeGap("开始邀请指导老师-完成");
        return ResultInfoUtil.buildSuccess();
    }

    @GetMapping("/sign/invite/accept")
    @ApiOperation("报名活动：8-接收邀请")
    @OperLog(type = OperEnum.ADD, description = "接收邀请")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> acceptInvitation(@RequestParam String token) {
        /*
        1.通过token查询邀请是否存在或者过期
        2.如果邀请正常则判断当前用户是否满足条件
            （1.学生-不能加入同活动的多个队伍  token-》活动id-》teamid列表-》在team_member表中，type=1，对应userid）
            （2.老师-作为指导老师只能参与一个团队  token-》活动id-》teamid列表-》在team_member表中，type=2，对应userid ，作为参与老师则同学生）
        3.如果满足条件，插入t_activity_team_member表
            （邀请人id，活动id-》teamid，currentUser-》userid，type）
         */
        //判断token
        QueryWrapper<ActivityTeamMemberInvite> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("token", token);
        ActivityTeamMemberInvite inviteInfo = inviteService.getOne(queryWrapper);
        if (inviteInfo == null) {
            return ResultInfoUtil.buildError("您未收到该邀请");
        } else if (inviteInfo.getTokenValidTime().before(new Date())) {
            return ResultInfoUtil.buildError("该邀请已过期");
        }

        //判断用户是否满足条件
        List<Long> teamIdList = activitySignService.selectTeamIdByActivityId(inviteInfo.getActivityId());
        List<TeamMember> teamMemberList = teamMemberService.listByIds(teamIdList);
        for (TeamMember teamMember : teamMemberList) {
            if (teamMember.getType().equals(1) && teamMember.getUserId().equals(RequestUtil.getCurrentUserId())) {
                return ResultInfoUtil.buildError("您已经加入该活动的其他队伍，无法加入同一活动的更多队伍");
            } else if (teamMember.getType().equals(2) && teamMember.getUserId().equals(RequestUtil.getCurrentUserId())) {
                return ResultInfoUtil.buildError("您已经指导了其他队伍，无法指导更多队伍");
            }
        }
        //判断被邀请人是否是其他队伍的队长,(teamidlist->teamid->useridlist 与currentuser对比)
        List<ActivityTeam> activityTeams = activitySignService.listByIds(teamIdList);
        for (ActivityTeam activityTeam : activityTeams) {
            if (RequestUtil.getCurrentUserId().equals(activityTeam.getUserId())) {
                return ResultInfoUtil.buildError("您已经是该活动的其他队伍的队长，无法接受转让队长的邀请");
            }
        }

        Long teamId = activitySignService.selectTeamIdByUserIdAndActivityId(inviteInfo.getUserId(), inviteInfo.getActivityId());
        //如果是转让队长，则需修改t_activity_team表中userid为当前id；修改t_activity_team_member为token对应的userid
        if (inviteInfo.getType() == ActivityTeamMemberInviteEnum.INVITE_AS_TEAM_LEADER.getIndex()) {
            //修改t_activity_team表
            var activityTeamToSave = ActivityTeam.builder()
                    .id(teamId)
                    .userId(RequestUtil.getCurrentUserId())
                    .build();
            activitySignService.updateById(activityTeamToSave);
            //修改t_activity_team_member表
            UpdateWrapper<TeamMember> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("team_id", teamId)
                    .eq("user_id", RequestUtil.getCurrentUserId());
            updateWrapper.set("user_id", inviteInfo.getUserId());
            teamMemberService.update(updateWrapper);
        } else {
            //其他情况则正常保存进t_activity_team_member表中
            var teamMemberToSave = TeamMember.builder()
                    .teamId(teamId)
                    .userId(RequestUtil.getCurrentUserId())
                    .type(inviteInfo.getType())
                    .build();
            teamMemberService.save(teamMemberToSave);
        }
        return ResultInfoUtil.buildSuccess();
    }

    @PostMapping("/sign/change/teamleader/{teamId}/{memberId}")
    @ApiOperation("报名活动：9-转让队长")
    @OperLog(type = OperEnum.UPDATE, description = "转让队长")
    public ResultInfo<Void> changeTeamLeader(@PathVariable("teamId") Long teamId, @PathVariable("memberId") Long memberId) {
        /*
        1.判断当前用户是否是该活动队伍队长(teamid->userid 与 currentuser 对比)
        2.如果是，判断被选中用户是否是当前活动队员(teamid->userid列表, 逐个比对或者 contain)
        3.如果是，直接转让(不需要被邀请人同意?  走邀请的流程  )(修改表中userid，根据teamid查找)
         */
        //判断当前用户是否是队长
        if (!RequestUtil.getCurrentUserId().equals(activitySignService.selectUserIdByTeamId(teamId))) {
            return ResultInfoUtil.buildError("您不是当前队伍的队长，无法进行转让");
        }
        //判断被选中用户是否是当前活动队伍的队员
        QueryWrapper<TeamMember> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("team_id", teamId)
                .eq("user_id", memberId);
        if (teamMemberService.count(queryWrapper) < 1) {
            return ResultInfoUtil.buildError("被邀请人不是您队伍中的成员，无法进行转让");
        }
        //给被邀请人发送转让邀请
        User currentUser = userService.findUser(RequestUtil.getCurrentUserId());
        String activityTitle = activityService.getById(activitySignService.getById(teamId).getActivityId()).getTitle();
        String activityTeamName = activitySignService.getById(teamId).getName();
        String token = ValidateUtils.createValidateString(16);
        String context = currentUser.getUsername() + "邀请您成为【" + activityTitle
                + "】活动的【" + activityTeamName + "】队伍的队长,如果您同意邀请，请在24小时内点击下方链接:"
                + Constants.APS_BASE_URL + "token?" + token;
        sendMailService.sendInformEmail(userService.findUser(memberId).getEmail(), context);
        //插入邀请信息表
        var now = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, 1);
        Date nextDay = calendar.getTime();
        var teamMemberInviteToSave = ActivityTeamMemberInvite.builder()
                .userId(RequestUtil.getCurrentUserId())
                .type(ActivityTeamMemberInviteEnum.INVITE_AS_TEAM_LEADER.getIndex())
                .activityId(activitySignService.getById(teamId).getActivityId())
                .token(token)
                .tokenValidTime(nextDay)
                .createTime(now)
                .build();
        inviteService.save(teamMemberInviteToSave);
        return ResultInfoUtil.buildSuccess();
    }

    @DeleteMapping("/sign/remove/member/{teamId}/{memberId}")
    @ApiOperation("报名活动：10-移除成员/指导老师")
    @OperLog(type = OperEnum.DELETE, description = "移除成员/指导老师")
    public ResultInfo<Void> removeTeamMember(@PathVariable("teamId") Long teamId, @PathVariable("memberId") Long memberId) {
        /*
        1.判断当前用户是否是该活动队伍的队长
        2.如果是，判断待移除的用户是否是该队伍的成员/指导老师(查出teammember列表，挨个比对)
        3.如果是，邮件通知并删除表中数据
         */
        //判断当前用户是否是队长
        if (!RequestUtil.getCurrentUserId().equals(activitySignService.selectUserIdByTeamId(teamId))) {
            return ResultInfoUtil.buildError("您不是该活动队伍的队长，无法进行操作");
        }
        //判断待移除的用户是否是该队伍的成员
        boolean flag = false;
        List<TeamMember> teamMemberList = teamMemberService.list();
        for (TeamMember teamMember : teamMemberList) {
            if (teamMember.getTeamId().equals(teamId) && teamMember.getUserId().equals(memberId)) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            return ResultInfoUtil.buildError("待移除用户不是该队伍成员，无法进行操作");
        }

        //邮件通知并删除
        String context = "【" + activityService.getById(activitySignService.getById(teamId).getActivityId()).getTitle()
                + "】活动的【" + activitySignService.getById(teamId).getName() + "】队伍的队长将您移出了该队伍。";
        sendMailService.sendInformEmail(userService.findUser(memberId).getEmail(), context);
        QueryWrapper<TeamMember> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("team_id", teamId)
                .eq("user_id", memberId);
        teamMemberService.remove(queryWrapper);
        return ResultInfoUtil.buildSuccess();
    }

    @DeleteMapping("/sign/exit/team/{teamId}")
    @ApiOperation("报名活动：11-成员主动退出队伍")
    @OperLog(type = OperEnum.DELETE, description = "成员主动退出队伍")
    public ResultInfo<Void> exitTeam(@PathVariable("teamId") Long teamId) {
        /*
        1.判断用户是否在小队内
        2.给队长发邮件
        3.删除表中数据
         */
        if (!teamMemberService.isMemberInTeam(RequestUtil.getCurrentUserId(), teamId)) {
            return ResultInfoUtil.buildError("您不在该小队内");
        }
        if (activitySignService.getById(teamId).getUserId().equals(RequestUtil.getCurrentUserId())) {
            return ResultInfoUtil.buildError("您是该小队的队长，不可随意退出小队");
        }

        //邮件通知并删除
        String context = "您在【" + activityService.getById(activitySignService.getById(teamId).getActivityId()).getTitle()
                + "】活动的【" + activitySignService.getById(teamId).getName() + "】队伍的"
                + userService.findUser(RequestUtil.getCurrentUserId()).getUsername() + "成员主动退出了您的队伍";
        sendMailService.sendInformEmail(userService.findUser(activitySignService.getById(teamId).getUserId()).getEmail(), context);
        QueryWrapper<TeamMember> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("team_id", teamId)
                .eq("user_id", RequestUtil.getCurrentUserId());
        teamMemberService.remove(queryWrapper);
        return ResultInfoUtil.buildSuccess();
    }

    @PostMapping("/feedback")
    @ApiOperation("报名活动：12-填写活动反馈")
    @OperLog(type = OperEnum.ADD, description = "填写活动反馈")
    @Transactional(rollbackFor = Exception.class)
    public ResultInfo<Void> completeActivityFeedback(@Valid @RequestBody FeedBackForm feedBackForm) {
        /*
        判断报名状态
         */
        ActivitySignEnum status = activitySignService.getById(feedBackForm.getTeamId()).getStatus();
        if (!(status.equals(ActivitySignEnum.ACTIVITY_ON) || status.equals(ActivitySignEnum.ACTIVITY_WAIT_FOR_FEEDBACK))) {
            return ResultInfoUtil.buildError("当前状态不允许填写/更改策划");
        }

        /*
        1.判断当前用户是否属于该队伍
         */
        if (!teamMemberService.isMemberInTeam(RequestUtil.getCurrentUserId(), feedBackForm.getTeamId())) {
            return ResultInfoUtil.buildError("您不属于该队伍，无法填写反馈");
        }
        if (teamFeedbackService.getById(feedBackForm.getTeamId()) != null) {
            return ResultInfoUtil.buildError("该队伍的活动反馈已经完成，无法重复填写");
        }

        //写入活动反馈表(查队长id-》队长学院)
        Long collegeId = null;
        /*
        获取学院id
         */
        Long userId = activitySignService.getById(feedBackForm.getTeamId()).getUserId();
        collegeId = userInfoService.selectCollegeIdByUserId(userId);
        var activityTeamFeedbackToSave = ActivityTeamFeedback.builder()
                .teamId(feedBackForm.getTeamId())
                .title(feedBackForm.getTitle())
                .author(feedBackForm.getAuthor())
                .collegeId(collegeId)
                .blog(feedBackForm.getBlog())
                .coverPicture(feedBackForm.getPicturePath())
                .build();
        teamFeedbackService.save(activityTeamFeedbackToSave);
        /*
        更改活动状态
         */
        var activityTeamToUpdate = ActivityTeam.builder()
                .id(feedBackForm.getTeamId())
                .status(ActivitySignEnum.ACTIVITY_COMPLETE)
                .build();
        activitySignService.updateById(activityTeamToUpdate);
        return ResultInfoUtil.buildSuccess();
    }

    @PutMapping("/feedback")
    @ApiOperation("报名活动：13-更改活动反馈")
    @OperLog(type = OperEnum.UPDATE, description = "更改活动反馈")
    public ResultInfo<Void> changeActivityFeedback(@RequestBody FeedBackForm feedBackForm) {
        /*
        判断报名状态
         */
        ActivitySignEnum status = activitySignService.getById(feedBackForm.getTeamId()).getStatus();
        if (!(status.equals(ActivitySignEnum.ACTIVITY_ON) || status.equals(ActivitySignEnum.ACTIVITY_WAIT_FOR_FEEDBACK))) {
            return ResultInfoUtil.buildError("当前状态不允许填写/更改策划");
        }

        /*
        1.判断当前用户是否属于该队伍
         */
        if (!teamMemberService.isMemberInTeam(RequestUtil.getCurrentUserId(), feedBackForm.getTeamId())) {
            return ResultInfoUtil.buildError("您不属于该队伍，无法填写反馈");
        }

        //写入活动反馈表
        var activityTeamFeedbackToChange = ActivityTeamFeedback.builder()
                .teamId(feedBackForm.getTeamId())
                .title(feedBackForm.getTitle())
                .author(feedBackForm.getAuthor())
                .blog(feedBackForm.getBlog())
                .lastEditDate(new Date())
                .coverPicture(feedBackForm.getPicturePath())
                .build();
        teamFeedbackService.updateById(activityTeamFeedbackToChange);
        return ResultInfoUtil.buildSuccess();
    }

    @GetMapping("/sign/questions")
    @ApiOperation("报名活动：14-获取报名活动时的问题")
    public ResultInfo<List<ActivityFormQuestionDto>> getSignQuestions(@RequestParam("activityId") Long activityId) {
        // 先查询活动对应的题目集
        ActivityForm activityForm = activityFormService.getById(activityId);
        // 根据题目集查找题目
        List<ActivityFormQuestion> activityFormQuestions = activityFormQuestionService.listByIds(CollectionUtil.separateStringExcludeEmpty(activityForm.getQuestions()));
        List<ActivityFormQuestionDto> activityFormQuestionDtos = new ArrayList<>();
        // 将题目选项拆分并传给前台
        for (ActivityFormQuestion activityFormQuestion : activityFormQuestions) {
            activityFormQuestionDtos.add(
                    ActivityFormQuestionDto.builder()
                            .id(activityFormQuestion.getId())
                            .questionName(activityFormQuestion.getQuestion())
                            .type(activityFormQuestion.getType())
                            .options(CollectionUtil.separateStringExcludeEmpty(activityFormQuestion.getOptions()))
                            .build()
            );
        }
        return ResultInfoUtil.buildSuccess(activityFormQuestionDtos);
    }
//
//    private void printTimeGap(String msg) {
//        final long cur = System.currentTimeMillis();
//        log.info("{}\t,{}\t, {}", msg, cur, cur - lastTime);
//        lastTime = cur;
//    }

}